package com.lnsoft.util;

import java.lang.reflect.Method;

/**
 * @author ChongQiang,Wang
 *
 * created time 2011-11-16 上午11:46:53
 * 
 *  参数：克隆所参考的对象
 *  返回：克隆后的对象 
 *  如果克隆则抛出一个异常  可能的原因有 找不到相应的 setter方法等 
 *  
 *  遍历传递进来的对象  public 的 getter方法，取得 get方法的返回类型，
 *  然后 对 setter方法进行赋值
 */
public class CloneObject {
	/**
	 *  请保证传进来的对象不是null，否则依然返回null
	 *  克隆对象是根据对象的public的setter和getter方法
	 *  如：如果传进来的是对象A，则返回的依然是A对象
	 */
	public static Object clone(Object obj){
		if(obj == null){
			System.out.println("传进来的对象为为空。无法克隆，直接返回原对象。");
			return obj;
		}
		Class<?> c = obj.getClass();
		Method [] ms = c.getMethods();
		Object o = null;
		try{
			o = c.newInstance();
		}catch(Exception e){
			throw new RuntimeException("克隆 " + c.getName() + " 出现异常");
		}
		for(Method m : ms){
			if(m.getName().startsWith("get") && !m.getName().equals("getClass")){
				Class<?> type_class = m.getReturnType();
				String filed_str = m.getName().substring(3);
				Method setMethod;
				try {
					setMethod = c.getMethod("set" + filed_str,m.getReturnType());
					setMethod.invoke(o, m.invoke(obj));
				} catch (Exception e) {
					throw new RuntimeException("克隆 " + c.getName() + " 出现异常");
				}
				
			}
		}
		return o;
	}
	/**
	 *  请保证传进来的两个对象都不是null，否则依然返回null
	 *  克隆对象是根据对象的public的setter和getter方法
	 *  
	 *  如：如果传进来的是对象obj，返回的是对象cloneObj
	 *  要保证它们的public的setter和getter方法相同，如果obj 有 10个public的getter方法，cloneObj 有8个与其对应的setter方法，
	 *  则 cloneObj的8个属性被赋值
	 */
	public static Object clone(Object obj,Object cloneObj){
		if(obj == null){
			System.out.println("传进来被克隆的对象为空。直接返回null");
			return null;
		}
		if(cloneObj == null){
			System.out.println("传进来克隆的目标对象为空。直接返回null");
			return null;
		}
		Class<?> c = obj.getClass();
		Class<?> cloneC = cloneObj.getClass();
		Method [] methods = c.getMethods();
		Method [] cloneMethods = cloneC.getMethods();
		
		for(Method m : methods){
			if(m.getName().startsWith("get") && !m.getName().equals("getClass")){
				for(Method cloneM : cloneMethods){
					if(m.getName().substring(3).equals(cloneM.getName().substring(3)) && cloneM.getName().startsWith("set")){
						try{
							cloneM.invoke(cloneObj, m.invoke(obj, null));
						}catch (Exception e) {
							throw new RuntimeException("克隆 " + c.getName() + " 出现异常");
						}
					}
				}
			}
		}
		
		return cloneObj;
	}
	public static Object clone(Object obj,Class<?> c){
		Object o = null;
		try {
			o = c.newInstance();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		return clone(obj,o);
	}

}
